iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
1

偶爾會看到鏈式寫法,但實際上自己寫package的時候,還不曾這樣玩過,這篇講解所謂的鏈式寫法,以及拿decimal package稍微做分析範例。

說明

在golang第一次接觸的相關部分,就是standard library的time package了,實務上開發很容易就需要使用時間的處理。

『鏈式』的寫法就如以下這段code示範

package main

import (
	"fmt"
	"time"
)

func main() {
	t1 := time.Now()

	time.Sleep(1)

	t2 := time.Now().Sub(t1).Seconds()
	fmt.Println(t2)
}

time的三個method可以連續使用對吧,Now()、Sub()、Seconds(),就像個鏈子鏈在一起。

time.Now().Sub(t1).Seconds()

而且基於golang的設計原則,method name大小寫用途有所區分,所以看到這樣的使用方式,看到的method name基本上都會是大寫,除非你自己設計在自己的package,然後在這個package做內部使用而已,那筆者認為這意義其實不大。

不過筆者第一次接觸chain (鏈式寫法)並非是在golang或php,而是在jquery,jquery容易在使用上一個method接著一個method連續使用,那時就很好奇地問前輩,這到底是什麼原理,為什麼我自己寫的method沒辦法給別人這樣很方便的使用?

前輩告訴我一句話:

『那就是每個method做回傳的時候,回傳它自己呀。』

核心概念的確是這樣,筆者沒什麼好補充的,因為每個method拿到的回傳結果,如果是一個物件,物件又有屬於它的method,當然可以接著繼續使用method囉。

decimal 怎麼寫的

如下圖舉例,我的程式接連使用了NewFromFloat()、Add()、Float64()

allPoint,_ := decimal.NewFromFloat(currentPoint).Add(decimal.NewFromFloat(incomePoint)).Float64()

於是我們來看看,這三個method詳細是怎麼寫的

NewFromFloat()

func NewFromFloat(value float64) Decimal {
	if value == 0 {
		return New(0, 0)
	}
	return newFromFloat(value, math.Float64bits(value), &float64info)
}

Add()

func (d Decimal) Add(d2 Decimal) Decimal {
	baseScale := min(d.exp, d2.exp)
	rd := d.rescale(baseScale)
	rd2 := d2.rescale(baseScale)

	d3Value := new(big.Int).Add(rd.value, rd2.value)
	return Decimal{
		value: d3Value,
		exp:   baseScale,
	}
}

Float64()

func (d Decimal) Float64() (f float64, exact bool) {
	return d.Rat().Float64()
}

NewFromFloat()和Add()回傳的都是Decimal型態,所以可以繼續使用任何一個屬於Decimal的method,直到Float64(),就不再回傳Decimal型態,作為一個收尾的method。

那是因為外面能用這個Decimal的型態的方式非常有限,就是該package大寫提供出去的field和method而已,所以提供method,將最後的型態處理成golang的通用型態回傳,非常的合理合情。

最後我們來看一下,decimal型態長什麼樣子

type Decimal struct {
	value *big.Int
	exp int32
}

是個內部擁有兩個小寫變數的struct,所以看來只能透過package提供的method,對內容做操作。

值得一提的是,因為內部的數值是可能因method的使用而做改變,所以在使用method的順序上,可能要稍微注意,像是deciaml這種做數值四則運算處理的package,也許安排很簡單,但是像是gorm那種組query語法,開始者要自己清楚知道,鏈式的使用上『順序』很重要,要知道自己究竟最後組出了什麼樣的語法。

以上,有興趣也可以自己寫看看鏈式設計的package囉。


上一篇
Day19 .[心得與討論篇] 走向interface去設計架構(6)- 進階變化
下一篇
Day21 .[心得與討論篇] struct 設計解析 - 以melody package (1)
系列文
Let's Eat GO ! 實務開發雜談by Golang30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言